React 具有強大的 composition 模型,在使用react的時候會建議使用Composition 而非繼承,因為composition是一種強大的模式,可以使您的組件增加可重用性。
** React Composition 是甚麼?**
Composition是將組件作為道具傳遞給其他組件,從而與其他組件一起創建新組件。
之前有提到,我們可以透過 props使我們的component 更加通用,這些 component 使用特殊的 children prop 將 children element 直接傳入到它們的輸出,但是有些組件可能不會提早知道他們的子prop是什麼,比如說sidebar就會和Dialog一樣通用[box]。
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
這是一個範例
</p>
</FancyBorder>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<WelcomeDialog />);
在上面範例中,任何在<FancyBorder>
範圍內的程式碼都會被視為props傳遞給FancyBorder component,被傳遞的 element 會在最終的輸出出現。
這是輸出結果
特別化
Welcome Dialog 是 Dialog 的一個特例。 這也不是繼承的例子。
特別化(Specialization)代表一個 component 是另一個通用 component 的特殊型態的狀況
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
function Dialog(props) {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{props.title}
</h1>
<p className="Dialog-message">
{props.message}
</p>
</FancyBorder>
);
}
function WelcomeDialog() {
return (
<Dialog
title="Welcome"
message="這是一個範例" />
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<WelcomeDialog />);
我們可以發現他把他們分成三部分,第一部分是FancyBorder(props),第二部分是Dialog(props),這部分只定義了邊框的顏色而已,並沒有將內容文字也一起定義,反而是又在創了{props.title}和{props.message},接著讓第三部份去定義title和message的字串。
而輸出結果也相同:
結尾:
Composition可以重新組織你的組件,其功能非常強大,可以使代碼更有條理,避免道具鑽探,且可以提高性能
props和Composition提供了靈活性以及使用安全的方式自定義組件外觀,而在facebook的開發中,也已經沒有再使用繼承作為創建組件層次結構的例子,可見其實用性。
參考文章:
https://reactjs.org/docs/composition-vs-inheritance.html
https://felixgerschau.com/react-component-composition/